package server_multicast;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.InetAddress;
import java.net.MulticastSocket;
import java.net.NetworkInterface;
import java.net.UnknownHostException;

/**
 * Klasa predstavlja multicast server, odnosno zaduzena je da prima multicast poruke poslate
 * od strane RLM klijenta. Server je registrovan u odredjenoj multicast grupi (IP adresi) i
 * prima sve multicast poruke namanjene toj grupi.
 * 
 * Kada se primi poruka formata GET_SERVER_INFO, startuje se MulticastProcessing thread,
 * koji obradjuje multicast poruku.
 * 
 * @author Uros Krkic
 */
public class ServerMulticast extends Thread {

	/**
	 * Buffer u koji se smesta primljena poruka.
	 */
	private byte[] buffer = new byte[65535];
	
	
	/**
	 * IP adresa koja predstavlja mutlicast grupu.
	 */
	private InetAddress multicastGroup = null;

	
	/**
	 * Multicast multicastPort.
	 */
	private int multicastPort = 0;
	
	
	/**
	 * Datagram paket koji se prima kao poruka.
	 */
	private DatagramPacket packet = null;

	
	/**
	 * Multicast socket.
	 */
	private MulticastSocket multicastSocket = null;

	
	/**
	 * Network interface.
	 */
	private NetworkInterface networkInterface = null;
	
	
	/**
	 * LAN IP adresa servera.
	 */
	private InetAddress hostAddress = null;
	
	
	
	/**
	 * Konstruktor.
	 * @author Uros Krkic
	 */
	public ServerMulticast(InetAddress groupAddress, int port) {
		this.multicastGroup = groupAddress;
		this.multicastPort = port;
		
		try {
			packet = new DatagramPacket(buffer, buffer.length);
			
			if ( !multicastGroup.isMulticastAddress() ) {
				this.interrupt();
				return;
			}
			
			multicastSocket = new MulticastSocket(port);

			
			String hostName = InetAddress.getLocalHost().getHostName();			

			/*
			 *	Ukoliko postoji vise mreznih adaptera, na istom racunaru, sa IP adresom koja u prefiksu
			 *  sadrzi 192.168.., ova implementacija ne garantuje pronalazenje ispravnog
			 *  adaptera.
			 *  Ovako je uradjeno, jer u RAF-ovoj mrezi sve IP adrese pocinju sa 192.168.
			 */
			for (int i = 0; i < InetAddress.getAllByName(hostName).length; i++) {
				
				hostAddress = InetAddress.getAllByName(hostName)[i];
			
				if ( (InetAddress.getAllByName(hostName)[i].getHostAddress().startsWith("192.168."))  ) {
					hostAddress = InetAddress.getAllByName(hostName)[i];
				}
			}
			
			
//			networkInterface = NetworkInterface.getByInetAddress(InetAddress.getLocalHost());
			networkInterface = NetworkInterface.getByInetAddress(hostAddress);

			if ( networkInterface.isLoopback() == false && networkInterface.isUp() ) {
				multicastSocket.setNetworkInterface(networkInterface);
			}

			multicastSocket.joinGroup(multicastGroup);
			
		}
		catch (UnknownHostException e) {
			System.err.println(e);
		}
		catch (IOException ioe) {
			ioe.printStackTrace();
		}

		this.start();
	}

	
	@Override
	public void run() {

		printStartupMessage();

		try {
			while (true) {
				multicastSocket.receive(packet);
				
				String message = new String(packet.getData(), 0, packet.getLength());
				
				System.out.println("RECEIVED: " + message);
				
				if ( !message.startsWith("GET_SERVER_INFO") ) {
					continue;
				}
				
				/*
				 * Procesiranje primljene multicast poruke.
				 */
				new MulticastProcessing(this, message);
			}
		} catch (IOException ioe) {
			ioe.printStackTrace();
		}
	}
	
	
	
	/**
	 * Vraca IP adresu servera.
	 * @return
	 */
	public InetAddress getServerMCAddress() {
		return hostAddress;
	}
	
	
	
	/**
	 * Metod ispisuje startup poruku.
	 * @author Uros Krkic
	 */
	private void printStartupMessage() {
		StringBuffer messageBuffer = new StringBuffer();
		
		messageBuffer.append("Multicast thread started at:\n");
		messageBuffer.append("IP group: ");
		messageBuffer.append(multicastGroup.getHostAddress());
		messageBuffer.append("\nPort: ");
		messageBuffer.append(multicastPort);
		messageBuffer.append("\n============================");
		
		System.out.println(messageBuffer.toString());
	}

}
